﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using LEET.CommonInterfaces.Factories;
using LEET.CommonInterfaces.Automation;
using System.Windows;
using LEET.CommonInterfaces.Models;
using CommonInterfaces.Models;
using LEET.CommonInterfaces;
using LEET.LEETCommon.AutomationAbstractions;
using LEET.LEETCommon.Model;
using System.Windows.Automation;
using LEET.Exceptions.Models;
using Tedds_Tool.Instructions.Actions;
using StandardScriptItems.SimpleControls;
using System.Windows.Controls;
using System.Windows.Input;

namespace Tedds_Tool.Automatables
{
    public class Transformable : ILEETActionModule
    {
        public void Initialize()
        {
        }

        public AutomationElementEventListener CreateListener(IObservableWidget elem, IRegistryAccessor reg)
        {
            return new EventListener(elem, reg);
        }

        public bool CanCompile(string instruction)
        {
            try
            {
                String[] parts = Instruction.ParseInstruction(instruction);
                return "ACTION".Equals(parts[0]) && TypeName.Equals(parts[1]);
            }
            catch (InvalidInstructionException)
            {
                return false;
            }
        }

        public IInstruction CreateInstruction(string instruction)
        {
            return new Move(Instruction.ParseInstruction(instruction));
        }

        public string TypeName
        {
            get { return "MOVE"; }
        }

        public FrameworkElement CreateScriptItemDetails(Nil onUpdate, IEnumerable<string> processes, IElementState state)
        {
            ElementStateComboBox elem = new ElementStateComboBox(state);
            ScriptItemArgument arg1 = new ScriptItemArgument(elem, "-- X --");
            arg1.Name = "Argument1";
            ScriptItemArgument arg2 = new ScriptItemArgument(arg1, "-- Y --");
            arg2.Name = "Argument2";
            return arg2;
        }

        private class EventListener : AutomationElementEventListenerBase
        {
            AutomationEventHandler handler;
            AutomationPropertyChangedEventHandler propertyHandler;
            StructureChangedEventHandler structHandler;
            MouseEventHandler mouseHandler;
            private IRegistryAccessor registry;

            public EventListener(IObservableWidget target, IRegistryAccessor reg)
            {
                this.RootTarget = target;
                this.registry = reg;
                Listening = false;
                //buttonHandler = new MouseButtonEventHandler(ButtonEvent);
                //buttonHandler += Mouse.MouseDownEvent;
                //eve = new RoutedEventHandler(ButtonRoutedEvent);
                //eve += Mouse.MouseDownEvent;
                //AddMouseHandler(target.ae, buttonHandler);
                mouseHandler = new MouseEventHandler(ButtonEvent);
                try
                {
                    propertyHandler = new AutomationPropertyChangedEventHandler(CatchEvent);
                    structHandler = new StructureChangedEventHandler(CatchEvent);
                    registry.RegisterEventHandler(RootTarget.ae, structHandler);
                    registry.RegisterEventHandler(AutomationElement.BoundingRectangleProperty, RootTarget.ae, propertyHandler);
                    Listening = true;
                    
                }
                catch (ArgumentException) { }
            }
            
            //Mouse.MouseDownEvent = EventManager.RegisterRoutedEvent("MouseDown", RoutingStrategy.Bubble, typeof(MouseButtonEventHandler), typeof(Mouse));
            //public static readonly RoutedEvent MouseDownEvent = EventManager.RegisterRoutedEvent("MouseDown", RoutingStrategy.Bubble, typeof(MouseButtonEventHandler), typeof(Mouse));
            //public static readonly RoutedEvent MouseUpEvent = EventManager.RegisterRoutedEvent("MouseUp", RoutingStrategy.Bubble, typeof(MouseButtonEventHandler), typeof(Mouse));

            public void AddMouseHandler(AutomationElement ae)
            {
                //DependencyObject element = null;
                //((UIElement)element).AddHandler(Mouse.MouseDownEvent, mouseHandler);
                //(ae as FrameworkElement).AddHandler(Mouse.MouseDownEvent, mouseHandler);
                //((UIElement)ae).AddHandler(Mouse.MouseDownEvent, mouseHandler);
                //((UIElement)ae).AddHandler(Mouse.MouseUpEvent, mouseHandler);
            }

            //public static void RemoveMouseHandler(DependencyObject element, MouseButtonEventHandler handler)
            //{
            //    ((UIElement)element).RemoveHandler(Mouse.MouseDownEvent, handler);
            //    ((UIElement)element).RemoveHandler(Mouse.MouseUpEvent, handler);
            //}

            public override void Listen(IObservableWidget widget, string programmaticName, string newValue)
            {
                //In case element disappeared before it could be processed
                if (widget == null)
                    return;
                //if ((System.Windows.Forms.Control.MouseButtons ^ System.Windows.Forms.MouseButtons.Left) != System.Windows.Forms.MouseButtons.Left)
                //if ((System.Windows.Forms.Control.MouseButtons & System.Windows.Forms.MouseButtons.Left) != System.Windows.Forms.MouseButtons.Left)

                //System.Threading.Thread t = new System.Threading.Thread(new System.Threading.ThreadStart(MouseReleased));
                //t.SetApartmentState(System.Threading.ApartmentState.STA);
                //t.Start();
                //t.Join();

                //if(System.Windows.Input.Mouse.LeftButton == System.Windows.Input.MouseButtonState.Released)


                if(LeftButton)
                {
                    LeftButton = false;
                    //each target root element should have a HierarchyFinder
                    string fullpath = HierarchyFinder.GetPathFromHierarchy(widget);
                    AutomationElement old = HierarchyFinder.GetElementFromHierarchy(widget);

                    object obj;
                    bool implemented = widget.ae.TryGetCurrentPattern(TransformPattern.Pattern, out obj);
                    if (implemented)
                    {
                        TransformPattern patt = obj as TransformPattern;
                        if (patt.Current.CanMove && old.Cached.BoundingRectangle.Size == widget.ae.Current.BoundingRectangle.Size)
                            Delagate(new Event_Pair("ACTION\t| MOVE | " + fullpath + " | " + widget.ae.Current.BoundingRectangle.X + " | " + widget.ae.Current.BoundingRectangle.Y), widget.ae);
                        else if (patt.Current.CanResize)
                            Delagate(new Event_Pair("ACTION\t| RESIZE | " + fullpath + " | " + widget.ae.Current.BoundingRectangle.Size.Width + " | " + widget.ae.Current.BoundingRectangle.Size.Height), widget.ae);
                        //else if (patt.Current.CanRotate)
                        //{

                        //    Delagate(new Event_Pair("ACTION\t| ROTATE | " + fullpath + " | "), widget.ae);
                        //}
                    }

                    HierarchyFinder.SetUIAHierarchy(RootTarget);
                }
            }
            
            private bool LeftButton = false;
            public delegate void RoutedEventHandler(object sender, RoutedEventArgs e);
            public event RoutedEventHandler eve;
            public event MouseButtonEventHandler buttonHandler;
            public delegate void MouseButtonEventHandler(object sender, MouseButtonEventArgs e);
            private void ButtonEvent(object sender, MouseButtonEventArgs e)
            {
                if (e.LeftButton == MouseButtonState.Released)
                    LeftButton = true;
                else
                    LeftButton = false;
            }

            private void ButtonEvent(object sender, MouseEventArgs e)
            {
                if (e.LeftButton == MouseButtonState.Released)
                    LeftButton = true;
                else
                    LeftButton = false;
            }

            private void ButtonRoutedEvent(object sender, RoutedEventArgs e)
            {
                if (Mouse.LeftButton == MouseButtonState.Released)
                    LeftButton = true;
                else
                    LeftButton = false;
            }

            public override void Listen(IObservableWidget widget, string property)
            {
                //In case element disappeared before it could be processed
                if (widget == null || widget.ae == null)
                    return;

                //each target root element should have a HierarchyFinder
                string fullpath = HierarchyFinder.GetPathFromHierarchy(widget);
                AutomationElement old = HierarchyFinder.GetElement(fullpath, widget.ae);

                object obj;
                bool implemented = widget.ae.TryGetCurrentPattern(TransformPattern.Pattern, out obj);
                if (implemented)
                {
                    TransformPattern patt = obj as TransformPattern;
                    if (patt.Current.CanResize && old.Cached.BoundingRectangle.Location == widget.ae.Current.BoundingRectangle.Location)
                        Delagate(new Event_Pair("ACTION\t| RESIZE | " + fullpath + " | " + widget.ae.Current.BoundingRectangle.Size.Width + " | " + widget.ae.Current.BoundingRectangle.Size.Height), widget.ae);
                    else if (patt.Current.CanMove)
                        Delagate(new Event_Pair("ACTION\t| MOVE | " + fullpath + " | " + widget.ae.Current.BoundingRectangle.X + " | " + widget.ae.Current.BoundingRectangle.Y), widget.ae);
                    else if (patt.Current.CanRotate)
                    {

                        Delagate(new Event_Pair("ACTION\t| ROTATE | " + fullpath + " | "), widget.ae);
                    }
                }

                HierarchyFinder.SetUIAHierarchy(RootTarget);
            }

            public override void Dispose()
            {
                registry.RegisterEventHandler(AutomationElement.BoundingRectangleProperty, RootTarget.ae, propertyHandler);
                base.Dispose();
            }
        }
    }
}
